package com.app.mail.service.impl;

import com.app.mail.dao.MailDao;
import com.app.mail.dto.StoreMailDto;
import com.app.mail.model.StoreMail;
import com.app.mail.service.MailService;
import com.app.store.Utils.AppTypeEnum;
import com.app.sysmodule.exception.ServiceException;
import com.app.sysmodule.utils.PropertyUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.imageio.ImageIO;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.SendFailedException;
import javax.mail.internet.MimeMessage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.util.*;

import static com.google.zxing.client.j2se.MatrixToImageConfig.BLACK;
import static com.google.zxing.client.j2se.MatrixToImageConfig.WHITE;

/**
 * Created by song on 2018/1/31.
 */
public class MailServiceImpl implements MailService {
    private static Logger log = Logger.getLogger(MailServiceImpl.class);
    @Autowired
    private MailDao mailDao;
    private StackTraceElement[] elements;

    public List<StoreMailDto> getMailManageList() throws ServiceException {
        List<StoreMailDto> list = new ArrayList<StoreMailDto>();
        try {
            List<StoreMail> storeMails = mailDao.findAll();
            if (null != storeMails && storeMails.size() > 0) {
                for (StoreMail mail : storeMails) {
                    StoreMailDto dto = new StoreMailDto();
                    dto.setId(mail.getId());
                    dto.setEmailAccount(mail.getEmailAccount());
                    dto.setUserName(mail.getUserName());
                    dto.setStationName(mail.getStationName());
                    dto.setRemark(mail.getRemark());
                    dto.setIsSend(mail.getIsSend());
                    dto.setCreateDate(mail.getCreateDate());
                    dto.setUpdateDate(mail.getUpdateDate());
                    list.add(dto);
                }
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return list;
    }

    @Override
    public void deleteMailManage(Long id) throws ServiceException {
        try {
            if (null != id) {
                mailDao.delete(id);
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    public StoreMailDto editMaiManage(Long id) throws ServiceException {
        StoreMailDto storeMailDto = new StoreMailDto();
        try {
            if (null != id) {
                StoreMail storeMail = mailDao.getById(id);
                if (null != storeMail) {
                    storeMailDto.setId(storeMail.getId());
                    storeMailDto.setEmailAccount(storeMail.getEmailAccount());
                    storeMailDto.setUserName(storeMail.getUserName());
                    storeMailDto.setStationName(storeMail.getStationName());
                    storeMailDto.setRemark(storeMail.getRemark());
                    storeMailDto.setIsSend(storeMail.getIsSend());
                }
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return storeMailDto;
    }

    @Override
    public void saveMailManage(StoreMail storeMail) throws ServiceException {
        try {
            if (null != storeMail) {
                if (null != storeMail.getId()) {
                    StoreMail storeMail1 =  mailDao.getById(storeMail.getId());
                    storeMail.setCreateDate(storeMail1.getCreateDate());
                    storeMail.setUpdateDate(new Date());
                    mailDao.update(storeMail);
                } else {
                    storeMail.setCreateDate(new Date());
                    storeMail.setUpdateDate(new Date());
                    mailDao.save(storeMail);
                }
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    @Override
    public void updateIsSend(String id, String isSend) throws ServiceException {
        try {
            Long tem = 0l;
            if (Long.parseLong(isSend) == 0) {
                tem = 1l;
            } else if (Long.parseLong(isSend) == 1) {
                tem = 0l;
            }
            mailDao.updateIsSend(Long.parseLong(id), tem);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 发送邮件
     */
    public void sendMail(String appVersion,String serverVersion,String size ,String time,String remark,String url,String type,String path,String bucketName) throws ServiceException {
        final String username = PropertyUtils.getProperty("mailUserName");
        final String password = PropertyUtils.getProperty("mailPassword");
        String systemOs = "";
        String systemOsName = "";
        if("acewill-test".equals(bucketName)){
            systemOs = "测试环境";
            systemOsName = "开发版";
        }else{
            systemOs = "正式环境";
        }
        Integer port = Integer.parseInt(PropertyUtils.getProperty("mailPort"));
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setHost("smtp.exmail.qq.com");//链接服务器
        javaMailSender.setPort(port);
        javaMailSender.setUsername(username);//账号
        javaMailSender.setPassword(password);//密码
        javaMailSender.setDefaultEncoding("UTF-8");
        final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
        Properties properties = new Properties();
        properties.setProperty("mail.smtp.auth", "true");//开启认证
        properties.setProperty("mail.debug", "true");//启用调试
        properties.setProperty("mail.smtp.connectiontimeout", "3000");//启用调试
        properties.setProperty("mail.smtp.timeout", "3000");//设置链接超时
        properties.setProperty("mail.smtp.port", "465");//设置端口
        properties.setProperty("mail.smtp.socketFactory.port", "465");//设置ssl端口
        properties.setProperty("mail.smtp.socketFactory.fallback", "false");
        properties.setProperty("mail.smtp.host", "smtp.exmail.qq.com");
        properties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
        Authenticator authenticator = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                // 重写验证方法，填写用户名，密码
                return new PasswordAuthentication(username, password);
            }
        };
        javaMailSender.setJavaMailProperties(properties);
        // 设置utf-8或GBK编码，否则邮件会有乱码


        try {
            MimeMessage msg = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(msg, true);
            helper.setFrom(username);
            String[] to = getReceiver();
            helper.setTo(to);
            helper.setSubject("易企"+systemOsName+"【"+AppTypeEnum.getNameByKey(type).getName()+"】更新至【"+appVersion+"】版本");
            String qrcodeName = geter(url,path);//生成二维码
            String imgPath = PropertyUtils.getProperty("download_url")+"qrcode/"+qrcodeName;
            log.info("imgPath:------"+imgPath);
            String body = mailBody(systemOs,appVersion,serverVersion,size,time,remark,url,imgPath,type);
            helper.setText(body, true);
            //发送邮件
            javaMailSender.send(msg);
        } catch (MailSendException e) {
            //发生异常  尝试获取可用邮箱地址进行第二次发送邮件通知
            Map<Object, Exception> map = e.getFailedMessages();
            Set<Map.Entry<Object, Exception>> s =map.entrySet();
            List<String> addrList = new ArrayList<String>();
            for(Map.Entry<Object, Exception> ms:s){
                SendFailedException ex =  (SendFailedException)ms.getValue();
                Address[] de = ex.getValidUnsentAddresses();
                for(int i =0;i<de.length;i++){
                    addrList.add(de[i].toString());
                    log.info("上传app客户端出现异常时过滤邮件地址："+de[i].toString());
                }
            }
            if(null != addrList && addrList.size()>0){
                try{
                    MimeMessage msg = javaMailSender.createMimeMessage();
                    MimeMessageHelper helper = new MimeMessageHelper(msg, true);
                    helper.setFrom(username);
                    helper.setTo(addrList.toArray(new String[addrList.size()]));
                    helper.setSubject("易企"+systemOsName+"【"+AppTypeEnum.getNameByKey(type).getName()+"】更新至【"+appVersion+"】版本");
                    String qrcodeName = geter(url,path);//生成二维码
                    String imgPath = PropertyUtils.getProperty("download_url")+"qrcode/"+qrcodeName;
                    log.info("imgPath:------"+imgPath);
                    String body = mailBody(systemOs,appVersion,serverVersion,size,time,remark,url,imgPath,type);
                    helper.setText(body, true);
                    //发送邮件
                    javaMailSender.send(msg);
                }catch (Exception e1){
                   e1.getStackTrace();
                }
            }

        }catch (Exception e){
            e.getMessage();
            System.out.println("---------------------------------------");
        }
    }
    /**
     * 封装邮件内容
     */
    public String mailBody(String osName,String appVersion,String serverVersion,String size ,String time,String remark,String url,String imgPath,String type) {
        StringBuffer sb = new StringBuffer();
                sb.append("<body>")
                .append("<p style='color:red;'>您好:</p>")
                .append("<p>"+osName+"有" + AppTypeEnum.getNameByKey(type).getName() + "客户端发布了一个新版本。</p>")
                .append("<p>版本信息如下:</p>")
                .append("<p>客户端版本号:"+appVersion+"</p>")
                .append("<p>服务端版本号:"+serverVersion+"</p>")
                .append("<p>大小:"+size+"</p>")
                .append("<p>发布时间:"+time+"</p>")
                .append("<p>描述:"+remark+"</p>")
                .append("<p><a href="+url+">点击安装</a></p>")
                .append("<p>如链接无法跳转，请复制以下链接到浏览器中打开</p>")
                .append("<p>"+url+"</p>")
                .append("<p><img src='"+imgPath+"'/></p>")
                .append("</body>");
        return sb.toString();
    }

    /**
     * 获取接收邮件人员
     * @return
     */
    public String[] getReceiver() {
        String[] str = null;
        try{
            List<String> list = mailDao.getAllReceiver();
            if(null!= list && list.size()>0){
                str = list.toArray(new String[0]);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return str;
    }
    /**
     * 生成二维码
     */
    public String geter(String url,String path)throws ServiceException{
        String imageType = "png";
        String result= null;
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 0);
        BufferedImage image = null;
        try{
            BitMatrix encode = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 300, 300, hints);
            //2、获取二维码宽高
            int codeWidth = encode.getWidth();
            int codeHeight = encode.getHeight();

            //3、将二维码放入缓冲流
            image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < codeWidth; i++) {
                for (int j = 0; j < codeHeight; j++) {
                    //4、循环将二维码内容定入图片
                    image.setRGB(i, j, encode.get(i, j) ? BLACK : WHITE);
                }
            }
            result = System.currentTimeMillis()+".png";
            File outPutImage = new File(path+"/qrcode/"+result);
            //如果图片不存在创建图片
            File folder = new File(path+"/qrcode/");
            if(!folder.exists()){
                folder.mkdirs();//创建目录
            }
            if(!outPutImage.exists()){
                outPutImage.createNewFile();
            }
            //5、将二维码写入图片
            ImageIO.write(image, imageType, outPutImage);

        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return result;
    }

}
